/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/*!
  \file			uservar_tests.cc
  \date			Dec 2011
  \author		TNick

  \brief		Contains the implementation for UserVar class


*//*


 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Please read COPYING and README files in root folder
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
//
//
//
//
/*  INCLUDES    ------------------------------------------------------------ */

#include	<pgscript.h>
#include	<pgscript_internal.h>

#include	<module.h>

#include	<build-in/uvarary.h>
#include	<build-in/uvarbool.h>
#include	<build-in/uvarchar.h>
#include	<build-in/uvarcolor.h>
#include	<build-in/uvardouble.h>
#include	<build-in/uvarint.h>
#include	<build-in/uvarstring.h>
#include	<build-in/uvartree.h>

#include	<pgsave/pgsqs.h>
#include	<pgsave/pgsxml.h>

#include	"uservar.h"

/*  INCLUDES    ============================================================ */
//
//
//
//
/*  DEFINITIONS    --------------------------------------------------------- */

using namespace PgScr;



/*  DEFINITIONS    ========================================================= */
//
//
//
//
/*  DATA    ---------------------------------------------------------------- */


/*  DATA    ================================================================ */
//
//
//
//
/*  CLASS    --------------------------------------------------------------- */


#ifdef	PGSCRIPT_TESTS

int	change_ack = 0;
int	req_change_ack = 0;

/* ------------------------------------------------------------------------- */
void	kbUserVarChange_t1		( const UserVar * the_change)
{
	Q_UNUSED( the_change );
	change_ack++;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void	kbUserVarChange_t2		( const UserVar * the_change)
{
	Q_UNUSED( the_change );

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
bool	kbUserVarValidate_t1	( UserVar * the_var, const VarStore & new_v )
{

	req_change_ack++;
	the_var->setVal( new_v );
	return true;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
bool	kbUserVarValidate_t2	( UserVar * the_var, const VarStore & new_v )
{
	Q_UNUSED( the_var );
	Q_UNUSED( new_v );

	req_change_ack++;
	return false;
}
/* ========================================================================= */



/* ------------------------------------------------------------------------- */
void				PgScr::Variable_Tests					(
		int & performed, int & succeded )
{
	QString		Outcm;
	performed = 0;
	succeded = 0;


	Session * new_s = createSession();
	Module * new_m = new Module( "test_module" );


	int test_sz = 1000;
	int i;
	int j = 0;
	bool b_ok =  true;
	qDebug() << "Now testing with a number of " << test_sz << " variables";
	UserVar ** mdl_l = (UserVar **)malloc( sizeof(UserVar *) * test_sz );
	UserVar ** mdl_itr = mdl_l;

	int have_kb_chg = 0;
	int have_kb_val = 0;

	for ( i = 0; i < test_sz; i++ )
	{
		switch ( j ){
		case	0:	{/* nr checked for !FL_PREDEF below */
			mdl_itr[i] = new UserVar( );

			break; }
		case	1:	{/* nr checked for !FL_PREDEF below */
			mdl_itr[i] = new UserVar( QString::number( i ) );
			break; }
		case	2:	{/* nr checked for !FL_PREDEF below */
			mdl_itr[i] = new UserVar( QString::number( i ), new_m );
			break; }
		case	3:	{/* nr checked for !FL_PREDEF below */
			mdl_itr[i] = new UserVar( QString::number( i ), new_s );
			break; }
		case	4:	{/* nr checked for FL_PREDEF below */
			mdl_itr[i] = new UserVar( QString::number( i ),
									  UserVar::FL_PREDEF);
			break; }
		case	5:	{/* nr checked for FL_PREDEF below */
			/* numbers starting with this must have callbacks */
			mdl_itr[i] = new UserVar( QString::number( i ),
									  UserVar::FL_PREDEF,
									  kbUserVarChange_t1);
			have_kb_chg++;
			break; }
		case	6:	{/* nr checked for FL_PREDEF below */
			/* nr checked for validator below */
			mdl_itr[i] = new UserVar( QString::number( i ),
									  UserVar::FL_PREDEF,
									  kbUserVarChange_t1,
									  kbUserVarValidate_t1);
			have_kb_chg++;
			have_kb_val++;
			break; }
		case	7:	{/* nr checked for FL_PREDEF below */
			/* nr checked for validator below */
			mdl_itr[i] = new UserVar( QString::number( i ),
									  UserVar::FL_PREDEF,
									  kbUserVarChange_t1,
									  kbUserVarValidate_t1,
									  new_m);
			have_kb_chg++;
			have_kb_val++;
			break; }
		case	8:	{/* nr checked for FL_PREDEF below */
			mdl_itr[i] = new UserVar( new_s, QString::number( i ),
									  UserVar::FL_PREDEF);
			break; }
		case	9:	{/* nr checked for FL_PREDEF below */
			mdl_itr[i] = new UserVar( new_s, QString::number( i ),
									  UserVar::FL_PREDEF,
									  kbUserVarChange_t1);
			have_kb_chg++;
			break; }
		case	10:	{/* nr checked for FL_PREDEF below */
			/* nr checked for validator below */
			mdl_itr[i] = new UserVar( new_s, QString::number( i ),
									  UserVar::FL_PREDEF,
									  kbUserVarChange_t1,
									  kbUserVarValidate_t1);
			have_kb_chg++;
			have_kb_val++;
			break; }
		default:	break;
		}
		j++; if ( j >= 10 ) j = 0;

	}

	for ( i = 0; i < test_sz; i++ )
	{
		if ( j == 0 )
		{
			mdl_itr[i]->setName( QString::number( i ) );
		}
		j++; if ( j >= 10 ) j = 0;
	}


	for ( i = 0; i < test_sz; i++ )
	{
		if ( mdl_itr[i]->name() != QString::number( i ) )
		{
			b_ok = false;
			break;
		}
	}
	if ( b_ok )	TEST_OK
			else	TEST_FAIL
			qDebug() << " - checking name() and setName()..." << Outcm;
	performed++; b_ok = true;

	for ( i = 0; i < test_sz; i++ )
	{
		if ( mdl_itr[i]->isReadOnly() )
		{
			b_ok = false;
			break;
		}
		if ( mdl_itr[i]->presentation().isEmpty() )
		{
			b_ok = false;
			break;
		}
		if ( j < 4 )
		{
			if ( mdl_itr[i]->isPredef() )
			{
				b_ok = false;
				break;
			}
		}
		else
		{
			if ( ! mdl_itr[i]->isPredef() )
			{
				b_ok = false;
				break;
			}
		}
		j++; if ( j >= 10 ) j = 0;
	}
	if ( b_ok )	TEST_OK
			else	TEST_FAIL
			qDebug() << " - checking read only, predefined and presentation..." << Outcm;
	performed++; b_ok = true;

	for ( i = 0; i < test_sz; i++ )
	{
		mdl_itr[i]->makePermanent();
	}
	for ( i = 0; i < test_sz; i++ )
	{
		if ( ! mdl_itr[i]->isPermanent() )
		{
			b_ok = false;
			break;
		}
	}
	if ( b_ok )
	{
		for ( i = 0; i < test_sz; i++ )
		{
			mdl_itr[i]->makeVolatile();
		}
		for ( i = 0; i < test_sz; i++ )
		{
			if ( mdl_itr[i]->isPermanent() && ( mdl_itr[i]->isPredef() == false ) )
			{
				b_ok = false;
				break;
			}
		}
	}
	if ( b_ok )	TEST_OK
			else	TEST_FAIL
			qDebug() << " - checking permanent flag..." << Outcm;
	performed++; b_ok = true;





	/* callback management */
	for ( i = 0; i < test_sz; i++ )
	{
		if ( mdl_itr[i]->hasCallback() )
		{
			if ( ( j < 5 ) || ( j == 8 ) )
			{	b_ok = false; break;	}
		}
		else
		{
			if ( ( j >= 5 ) && ( j != 8 ) )
			{	b_ok = false; break;	}
		}
		if ( mdl_itr[i]->delCallback( kbUserVarChange_t1 ) )
		{
			if ( ( j < 5 ) || ( j == 8 ) )
			{	b_ok = false; break;	}
		}
		else
		{
			if ( ( j >= 5 ) && ( j != 8 ) )
			{	b_ok = false; break;	}
		}

		if ( mdl_itr[i]->hasMultipleCallbacks() )
		{	b_ok = false; break;	}
		if ( ( j == 6 ) ||
			 ( j == 7 ) ||
			 ( j == 10 ))
		{
			if ( ! mdl_itr[i]->hasValidator() )
			{	b_ok = false; break;	}
			if ( mdl_itr[i]->validator() != kbUserVarValidate_t1 )
			{	b_ok = false; break;	}
		}
		else
		{
			if ( mdl_itr[i]->hasValidator() )
			{	b_ok = false; break;	}
			mdl_itr[i]->setValidator( kbUserVarValidate_t1 );
		}

		mdl_itr[i]->addCallback( kbUserVarChange_t1 );
		mdl_itr[i]->addCallback( kbUserVarChange_t2 );
		if ( ! mdl_itr[i]->hasMultipleCallbacks() )
		{	b_ok = false; break;	}


		j++; if ( j >= 10 ) j = 0;
	}
	if ( b_ok )	TEST_OK
			else	TEST_FAIL
			qDebug() << " - checking callbacks from constructors..." << Outcm;
	performed++; b_ok = true;





	/* signal the change and tigger the callbacks */
	for ( i = 0; i < test_sz; i++ )
	{
		mdl_itr[i]->signalChange();
	}
	if ( change_ack == test_sz )	TEST_OK
			else	TEST_FAIL
			qDebug() << " - calling callbacks ..." << Outcm;
	performed++; b_ok = true; change_ack = 0;



	/* directly change the values */
	for ( i = 0; i < test_sz; i++ )
	{
		switch	( j )		{
		case	0:	{
			mdl_itr[i]->setVal( i );
			break;}
		case	1:	{
			mdl_itr[i]->setVal( (qint64)i*30000 );
			break;}
		case	2:	{
			mdl_itr[i]->setVal( i < ( test_sz / 2 ) );
			break;}
		case	3:	{
			mdl_itr[i]->setVal( 'X' );
			break;}
		case	4:	{
			mdl_itr[i]->setVal( qRgb( 0xFF, 0x00, i * 0x10) );
			break;}
		case	5:	{
			mdl_itr[i]->setVal( QString( "Variable at index %1").arg( i ) );
			break;}
		case	6:	{
			mdl_itr[i]->setVal( "const char" );
			break;}
		case	7:	{
			mdl_itr[i]->setVal( i / 3 );
			break;}
		case	8:	{
			mdl_itr[i]->setValChar( 1234 );
			break;}
		case	9:	{
			mdl_itr[i]->setValColor( 0xFF0055 );
			break;}
		case	10:	{
			mdl_itr[i]->setVal( QColor(10, 20, 10 * i) );
			break;}

		default: break;
		}

		mdl_itr[i]->signalChange();
		j++; if ( j >= 10 ) j = 0;
	}

	int sub_performed = 0;
	int sub_succeded = 0;

	VarArray_Tests( sub_performed, sub_succeded );
	performed += sub_performed; succeded += sub_succeded;
	VarBool_Tests( sub_performed, sub_succeded );
	performed += sub_performed; succeded += sub_succeded;
	VarChar_Tests( sub_performed, sub_succeded );
	performed += sub_performed; succeded += sub_succeded;
	VarColor_Tests( sub_performed, sub_succeded );
	performed += sub_performed; succeded += sub_succeded;
	VarDbl_Tests( sub_performed, sub_succeded );
	performed += sub_performed; succeded += sub_succeded;
	VarInt_Tests( sub_performed, sub_succeded );
	performed += sub_performed; succeded += sub_succeded;
	VarStr_Tests( sub_performed, sub_succeded );
	performed += sub_performed; succeded += sub_succeded;
	VarTree_Tests( sub_performed, sub_succeded );
	performed += sub_performed; succeded += sub_succeded;


	/* directly change the values */
	change_ack = 0;
	j = 0;
	for ( i = 0; i < test_sz; i++ )
	{

		switch	( j )		{
		case	0:	{
			b_ok = mdl_itr[i]->changeVal( i );
			break;}
		case	1:	{
			b_ok = mdl_itr[i]->changeVal( (qint64)i*30000 );
			break;}
		case	2:	{
			b_ok = mdl_itr[i]->changeVal( i < ( test_sz / 2 ) );
			break;}
		case	3:	{
			b_ok = mdl_itr[i]->changeVal( 'X' );
			break;}
		case	4:	{
			b_ok = mdl_itr[i]->changeVal( qRgb( 0xFF, 0x00, 50) );
			break;}
		case	5:	{
			b_ok = mdl_itr[i]->changeVal( QString( "Variable at index %1").arg( i ) );
			break;}
		case	6:	{
			b_ok = mdl_itr[i]->changeVal( "const char" );
			break;}
		case	7:	{
			b_ok = mdl_itr[i]->changeVal( i / 3 );
			break;}
		case	8:	{
			b_ok = mdl_itr[i]->changeVal( QColor(10, 20, 12) );
			break;}

		default: break;
		}
		if ( ! b_ok ) break;
		j++; if ( j >= 9 ) j = 0;

	}
	if ( b_ok )	TEST_OK
			else	TEST_FAIL
			qDebug() << " - changeVal ..." << Outcm;
	performed++; b_ok = true;
	if  ( change_ack == test_sz )	TEST_OK
			else					TEST_FAIL
			qDebug() << " - signaled with changeVal ..." << Outcm;
	performed++; b_ok = true;


	/* saving values */
	PgSave::PgsQs save_engine;
	for ( i = 0; i < test_sz; i++ )
	{
		mdl_itr[i]->save( save_engine );
	}

	/* removing any trace of the variables */
	for ( i = 0; i < test_sz; i++ )
	{
		delete mdl_itr[i];
	}


	/** @todo blind load*/
	/** @todo simple load*/



	delete new_m;









	deleteSession( new_s );
}
/* ========================================================================= */
#endif


/*  CLASS    =============================================================== */
//
//
//
//
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
